'''
窗口显示图片，画矩形框，可鼠标调整矩形框 20240626
交互式改参数界面 步骤3
    卡扣1阈值
    卡扣2阈值
'''

import sys
import traceback

import cv2
import numpy
import numpy as np
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel
from PyQt5.QtCore import Qt, QRectF, QPointF, QLineF
from PyQt5.QtGui import QPainter, QPixmap, QImage, QPen, QColor, QFont, QCursor

import yaml
from log import saved_algo_param_dict

# def numpy_array_to_qpixmap(numpy_array):
#     """
#     将NumPy数组转换为QPixmap。
#     参数:
#     numpy_array: 包含图像数据的NumPy数组，格式通常是BGR或RGB。
#     """
#     try:
#         # 确保NumPy数组的数据类型为uint8，这是QImage要求的
#         assert numpy_array.dtype == np.uint8
#
#         # 根据图像的通道数决定QImage的格式
#         if numpy_array.shape[2] == 3:  # RGB图像
#             qimage_format = QImage.Format_RGB888
#         elif numpy_array.shape[2] == 4:  # RGBA图像
#             qimage_format = QImage.Format_RGBA8888
#         else:
#             raise ValueError("Unsupported number of channels")
#
#         # 需要注意的是，OpenCV读取的图像默认是BGR顺序，而QImage期望的是RGB，
#         # 因此如果是BGR图像，需要进行通道转换
#         if numpy_array.shape[2] == 3:  # BGR转RGB
#             numpy_array = numpy_array[:, :, ::-1]
#
#         # 创建QImage对象
#         height, width, channel = numpy_array.shape
#         bytes_per_line = 3 * width  # 对于RGB图像，每行的字节数
#         if channel == 4:  # 对于RGBA图像
#             bytes_per_line = 4 * width
#         image = QImage(numpy_array.data, width, height, bytes_per_line, qimage_format)
#         image = image.rgbSwapped()  # 如果是从BGR转过来的，这里可以交换回RGB（如果需要的话）
#
#         # 从QImage创建QPixmap
#         pixmap = QPixmap.fromImage(image)
#     except:
#         print(traceback.format_exc())
#     return pixmap

def array2pix(image, ismask=False):
    if len(image.shape) == 2:
        image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGRA)

    if image.shape[2] == 1:
        image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGRA)

    if image.shape[2] == 3:
        #image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
    #show1 = cv2.resize(image, (640, 480))
    if ismask:
        #image[:,:,3] = image[:,:,2]
        pass

    show1 = image
    #QtImg = QImage(show1.data, show1.shape[1], show1.shape[0], QImage.Format_BGR888)
    QtImg = QImage(
        show1.data, show1.shape[1], show1.shape[0], QImage.Format_ARGB32)
    pixmap = QPixmap(QtImg)
    return pixmap

def read_yaml(file_path):
    with open(file_path, 'r') as file:
        config = yaml.safe_load(file)
    return config


def write_yaml(data, file_path):
    with open(file_path, 'w') as file:
        yaml.safe_dump(data, file)
class ImageWithResizableBox(QWidget):
    def __init__(self, imagePath, threshold_list=[100,100]):
        super().__init__()
        self.imagePath = imagePath
        if isinstance(imagePath, numpy.ndarray):
            # self.pixmap = numpy_array_to_qpixmap(imagePath)
            self.pixmap = array2pix(imagePath)
        else:
            self.pixmap = QPixmap(imagePath)
        self.scale = 0.2
        self.pixmap = self.pixmap.scaled(int(self.pixmap.width()*self.scale), int(self.pixmap.height()*self.scale), Qt.KeepAspectRatio, Qt.SmoothTransformation)


        # self.rect2 = QRectF(590, 476, 100, 0)  # 初始矩形框位置和大小
        # self.line = QLineF(50, 100)  #
        self.handle_size = 10
        self.dragging = False
        self.dragging_listrect_listconer = [[False, False, False, False],[False, False, False, False]] # [[rect1],[rect2]]
        self.drag_start_pos = QPointF()
        self.dragged_handle = None

        self.initUI()
        # self.threshold_list = threshold_list # 要设置的阈值
        self.param_path = 'config/param.yaml'
        # self.param_path = r'D:\code\git\zxc\fuba_\project_format_fubatianxian\config/param.yaml'
        self.threshold_list = read_yaml(self.param_path)['step3']
        self.rect_list = [QRectF(591, 302, int(self.threshold_list[0]*self.scale), 0),
                          QRectF(590, 476, int(self.threshold_list[1]*self.scale), 0)] # 初始矩形框位置和大小；卡扣上，卡扣下

    def initUI(self):
        # self.layout = QVBoxLayout(self)
        # self.label = QLabel("双击图片加载，拖动矩形框的角来调整大小", self)
        # self.layout.addWidget(self.label)
        self.setWindowTitle('修改步骤2阈值')
        self.resize(self.pixmap.width(), self.pixmap.height())  # 调整窗口大小以适应图片
        pass

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawPixmap(0, 0, self.pixmap)

        painter.setRenderHint(QPainter.Antialiasing)
        # pen = QPen(QColor(255, 0, 0), 2)
        # painter.setPen(pen)


        # 绘制矩形，矩形边角方框
        for ind, rect in enumerate(self.rect_list):
            if ind == 0: # 卡扣上
                painter.setPen(QPen(QColor(255, 0, 0), 2))
            else:
                painter.setPen(QPen(QColor(0, 255, 0), 2))
            painter.drawRect(rect)
            for corner in [(rect.topLeft(), 1), (rect.topRight(), 2),
                           (rect.bottomRight(), 3), (rect.bottomLeft(), 4)]:
                painter.drawRect(corner[0].x() - self.handle_size // 2,
                                 corner[0].y() - self.handle_size // 2,
                                 self.handle_size, self.handle_size)

        # 设置字体
        font = QFont('Arial', 18)
        painter.setFont(font)

        painter.setPen(QPen(QColor(255, 0, 0), 2))
        # painter.drawText(50, 100, f'卡扣上:{self.rect_list[0].width()}') # 文字左下角的位置 (x, y)
        painter.drawText(800, 100, f'卡扣上阈值:{self.threshold_list[0]}')  # 文字左下角的位置 (x, y)
        painter.setPen(QPen(QColor(0, 255, 0), 2))
        painter.drawText(800, 150, f'卡扣下阈值:{self.threshold_list[1]}')  # 文字左下角的位置 (x, y)

    def mouseDoubleClickEvent(self, event):
        self.update()

    def mousePressEvent(self, event): # 鼠标按下
        try:
            print('xxxx')
            if event.button() == Qt.LeftButton:
                for rect_ind, rect in enumerate(self.rect_list):
                    self.rect = rect
                    for corner, handle_index in [(self.rect.topLeft(), 1), (self.rect.topRight(), 2),
                                                 (self.rect.bottomRight(), 3), (self.rect.bottomLeft(), 4)]:
                        print(event.globalPos()) # 全局坐标
                        print(event.pos())  # 局部坐标
                        print((event.globalPos() - self.mapToGlobal(corner.toPoint())).manhattanLength())
                        if (event.globalPos() - self.mapToGlobal(corner.toPoint())).manhattanLength() <= self.handle_size / 2:
                            # self.dragging = True # 拖动tag
                            # self.dragged_handle = handle_index
                            # self.drag_start_pos = event.globalPos() - self.mapToGlobal(corner.toPoint())
                            self.dragging_listrect_listconer[rect_ind][handle_index-1] = True  # 拖动tag
                            # 改变鼠标形状为“选中”或手势指示的光标
                            hand_cursor = QCursor(Qt.PointingHandCursor)
                            self.setCursor(hand_cursor)
                            # break
                        else:
                            self.dragging_listrect_listconer[rect_ind][handle_index - 1] = False
                # else:
                #     # 如果没有点击到手柄，尝试加载图片
                #     if not self.pixmap.isNull():
                #         return
                #     self.imagePath = "your_image_path_here.png"  # 替换为你的图片路径
                #     self.pixmap = QPixmap(self.imagePath)
                #     self.update()
        except:
            print(traceback.format_exc())


    def mouseMoveEvent(self, event): # 鼠标移动
        try:
            print('mouseMoveEvent')
            # if self.dragging:
            #     global_pos = event.globalPos()
            #     new_pos = global_pos - self.drag_start_pos
            #     if self.dragged_handle == 1:  # 左上角
            #         self.rect.setTopLeft(self.mapFromGlobal(global_pos))
            #     elif self.dragged_handle == 2:  # 右上角
            #         self.rect.setTopRight(self.mapFromGlobal(global_pos))
            #     elif self.dragged_handle == 3:  # 右下角
            #         self.rect.setBottomRight(self.mapFromGlobal(global_pos))
            #     elif self.dragged_handle == 4:  # 左下角
            #         self.rect.setBottomLeft(self.mapFromGlobal(global_pos))
            #     self.update() # 执行paintEvent()

            fun_list = [[self.rect_list[0].setTopLeft, self.rect_list[0].setTopRight, self.rect_list[0].setBottomRight, self.rect_list[0].setBottomLeft],
                        [self.rect_list[1].setTopLeft, self.rect_list[1].setTopRight, self.rect_list[1].setBottomRight, self.rect_list[1].setBottomLeft]
                        ]
            global_pos = event.globalPos()
            for rect_ind, dragging_listconer in enumerate(self.dragging_listrect_listconer):
                wid = self.rect_list[rect_ind].width()
                if wid == 0:
                    print(f'矩形宽度为0 {coner_ind}')
                    dragging_listconer[0] = False
                    dragging_listconer[3] = False
                for coner_ind, is_dragging in enumerate(dragging_listconer):
                    if is_dragging:
                        fun_list[rect_ind][coner_ind](self.mapFromGlobal(global_pos)) # 移动矩形角点
                        self.threshold_list[rect_ind] = self.rect_list[rect_ind].width()/self.scale

                # self.paintText()

            self.update()  # 执行paintEvent()
        except:
            print(traceback.format_exc())

    def mouseReleaseEvent(self, event): # 鼠标释放
        try:
            print('mouseReleaseEvent')
            param_dict = read_yaml('config/param.yaml')
            param_dict['step3'] = self.threshold_list
            # write_yaml(param_dict, self.param_path)
            # write_yaml(param_dict['step3'], self.param_path+'_step3.yaml')
            saved_algo_param_dict['step3'] = self.threshold_list
            self.setCursor(QCursor(Qt.ArrowCursor)) # 默认箭头

            self.dragging = False
            self.dragged_handle = None
            self.update()
        except:
            print(traceback.format_exc())

    def closeEvent(self, event):
        saved_algo_param_dict['step3'] = []

if __name__ == "__main__":
    app = QApplication(sys.argv)
    widget = ImageWithResizableBox(r"D:\data\240507fubatianxian\other\3Image__2024-05-07__14-43-13.jpg")  # 替换为初始图片路径
    widget.resize(widget.pixmap.width(), widget.pixmap.height())  # 调整窗口大小以适应图片
    widget.show()
    sys.exit(app.exec_())
